using System;
using System.Collections.Generic;
using System.Text;

namespace RedPoint
{
    public class NodeLine
    {
        public string NodeName;
        public string ParentName;
    }
    public class Node
    {
        public List<Node> Parents { get; private set; } = new();
        public List<Node> Childs { get; private set; } = new();
        public string NodeName { get; private set; }
        public int ChildCount => Childs.Count;
        protected int count;
        public event Action<int> OnChangeEvent;

        public int GetCount() => count;

        public void SetCount(int value)
        {
            int current = Math.Max(0, value);
            if (current != count)
            {
                count = current;
                OnChangeEvent?.Invoke(count);
                // 递归通知所有父节点，带 visited 防环路
                var visited = new HashSet<Node>();
                foreach (var parent in Parents)
                    parent.OnChildCountChange(count, visited);
            }
        }

        public Node(string nodeName)
        {
            NodeName = nodeName;
        }

        public void AddChild(Node node)
        {
            if (!Childs.Contains(node))
                Childs.Add(node);
            if (!node.Parents.Contains(this))
                node.Parents.Add(this);
            node.OnChangeEvent += (v) =>
            {
                var visited = new HashSet<Node>();
                OnChildCountChange(v, visited);
            };
        }

        // 递归时传入 visited
        protected void OnChildCountChange(int value, HashSet<Node> visited)
        {
            if (visited.Contains(this))
                return;
            visited.Add(this);

            count = 0;
            foreach (var item in Childs)
                count += item.GetCount();
            OnChangeEvent?.Invoke(count);

            foreach (var parent in Parents)
                parent.OnChildCountChange(count, visited);
        }

        public void GetString(StringBuilder sb, string intent, Action<Node, string> makeStr)
        {
            foreach (var child in Childs)
            {
                var newintent = intent + "│  ";
                sb.Append(newintent);
                makeStr(child, newintent);
            }
        }
    }
}
